﻿using log4net;
using log4net.Config;
using log4net.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using xycn.ILogHelper;
using System.Threading.Tasks;

namespace xycn.common
{
    /// <summary>
    /// 日志辅助类，基于 log4实现 
    /// mrking 2021-03-14
    /// </summary>
    public class LogHelper
    {
        private static LogHelperImplement logHelperInstance = 
            new LogHelperImplement();

        /// <summary>
        /// 普通信息
        /// </summary>
        /// <param name="msg"></param>
        public static void Info(string msg, bool is_debug)
        {
            logHelperInstance.Info(msg, is_debug);
        }

        /// <summary>
        /// 普通信息
        /// </summary>
        /// <param name="msg"></param>
        public static void Info(string msg)
        {
            logHelperInstance.Info(msg);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="repmsg"></param>
        /// <param name="resmsg"></param>
        public static void Info(string msg, object repmsg = null, object resmsg = null)
        {
            logHelperInstance.Info(msg, repmsg, resmsg);
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="remark"></param>
        /// <param name="reqdata"></param>
        public static void Error(Exception ex, string remark, object reqdata = null)
        {
            logHelperInstance.Error(ex, remark, reqdata);
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="remark"></param>
        /// <param name="reqdata"></param>
        public static void Exception(Exception ex, string remark, object reqdata = null, object resdata = null)
        {
            logHelperInstance.Exception(ex, remark, reqdata);
        }
    }

    /// <summary>
    /// 类工厂，数据库接口库，需要同时实现该接口
    /// </summary>
    public class LogHelperFactory : IPluginFactory.IPluginFactory
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public override ILogHelper.ILogHelper CreatePlugin()
        {
            LogHelperImplement logHelperImplement
                 = new LogHelperImplement();
            return logHelperImplement;
        }
    }

    /// <summary>
    /// 实现日志接口
    /// </summary>
    public class LogHelperImplement : ILogHelper.ILogHelper
    {
        /// <summary>
        /// log4net配置
        /// </summary>
        private static ILoggerRepository lLogRepository = LogManager.CreateRepository("Logs");

        private static ILog iLogInfo = LogManager.GetLogger(lLogRepository.Name, "infoLog");
        private static ILog iLogError = LogManager.GetLogger(lLogRepository.Name, "logerror");

        private FileInfo fileInfo = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "Config/log4net.config");

        /// <summary>
        /// 普通信息
        /// </summary>
        /// <param name="msg"></param>
        public void Info(string msg, bool is_debug)
        {
            if (is_debug)
            {
                ConsoleWrite("[信息]", msg,
                    ConsoleWriteStyle.Infor);
            }
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Info("\r\n" + msg);
        }

        /// <summary>
        /// 普通信息
        /// </summary>
        /// <param name="msg"></param>
        public void Info(string msg)
        {
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Info("\r\n" + msg);
        }

        /// <summary>
        /// 用于记录普通信息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="repmsg"></param>
        /// <param name="resmsg"></param>
        public void Info(string msg, object repmsg = null, object resmsg = null, bool is_debug = true)
        {
            if (is_debug)
            {
                ConsoleWrite("[信息]", "\r\n" + msg + "\r\n入参:" + repmsg.ToJsonString() + "\r\n回参:" + resmsg,
                    ConsoleWriteStyle.Infor);
            }
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Info("\r\n" + msg + "\r\n入参:" + repmsg.ToJsonString() + "\r\n回参:" + resmsg);
        }

        /// <summary>
        /// 用于记录告警信息
        /// </summary>
        /// <param name="msg"></param>
        public void Warn(string msg, bool is_debug = true)
        {
            if (is_debug)
            {
                ConsoleWrite("[告警]", msg,
                    ConsoleWriteStyle.Warning);
            }
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Warn("\r\n" + msg);
        }

        /// <summary>
        /// 用于记录告警信息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="repmsg"></param>
        /// <param name="resmsg"></param>
        public void Warn(string msg, object repmsg = null, object resmsg = null, bool is_debug = true)
        {
            if (is_debug)
            {
                ConsoleWrite("[告警]", "\r\n" + msg + "\r\n入参:" + repmsg.ToJsonString() + "\r\n回参:" + resmsg,
                    ConsoleWriteStyle.Warning);
            }
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Warn("\r\n" + msg + "\r\n入参:" + repmsg.ToJsonString() + "\r\n回参:" + resmsg);
        }

        /// <summary>
        /// 用于记录主动发现的错误
        /// </summary>
        /// <param name="msg"></param>
        public void Error(string msg, bool is_debug = true)
        {
            if (is_debug)
            {
                ConsoleWrite("[错误]", msg,
                    ConsoleWriteStyle.Error);
            }
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Error("\r\n" + msg);
        }

        /// <summary>
        /// 用于记录主动发现的错误
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="repmsg"></param>
        /// <param name="resmsg"></param>
        public void Error(string msg, object repmsg = null, object resmsg = null, bool is_debug = true)
        {
            if (is_debug)
            {
                ConsoleWrite("[错误]", "\r\n" + msg + "\r\n入参:" + repmsg.ToJsonString() + "\r\n回参:" + resmsg,
                    ConsoleWriteStyle.Error);
            }
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            iLogInfo.Error("\r\n" + msg + "\r\n入参:" + repmsg.ToJsonString() + "\r\n回参:" + resmsg);
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="remark"></param>
        /// <param name="reqdata"></param>
        public void Error(Exception ex, string remark, object reqdata = null, bool is_debug = true)
        {
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            var errmsg = CreateErrorMessage(ex, remark);
            iLogError.Error(errmsg + new { reqdata }.ToJsonString());
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="remark"></param>
        /// <param name="reqdata"></param>
        public void Exception(Exception ex, string remark, object reqdata = null, object resdata = null, bool is_debug = true)
        {
            XmlConfigurator.Configure(lLogRepository, fileInfo);
            var errmsg = CreateErrorMessage(ex, remark);
            iLogError.Error(errmsg + new { reqdata, resdata }.ToJsonString());
        }

        /// <summary>
        /// 创建异常消息
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="remark">备注</param>
        /// <returns>结果</returns>
        private static StringBuilder CreateErrorMessage(Exception ex, string remark)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("************************Exception Start************************");
            string newLine = Environment.NewLine;
            stringBuilder.Append(newLine);
            stringBuilder.AppendLine("Exception Remark：" + remark);
            Exception innerException = ex.InnerException;
            stringBuilder.AppendFormat("Exception Date:{0}{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffff"), Environment.NewLine);
            if (innerException != null)
            {
                stringBuilder.AppendFormat("Inner Exception Type:{0}{1}", innerException.GetType(), newLine);
                stringBuilder.AppendFormat("Inner Exception Message:{0}{1}", innerException.Message, newLine);
                stringBuilder.AppendFormat("Inner Exception Source:{0}{1}", innerException.Source, newLine);
                stringBuilder.AppendFormat("Inner Exception StackTrace:{0}{1}", innerException.StackTrace, newLine);
            }
            stringBuilder.AppendFormat("Exception Type:{0}{1}", ex.GetType(), newLine);
            stringBuilder.AppendFormat("Exception Message:{0}{1}", ex.Message, newLine);
            stringBuilder.AppendFormat("Exception Source:{0}{1}", ex.Source, newLine);
            stringBuilder.AppendFormat("Exception StackTrace:{0}{1}", ex.StackTrace, newLine);
            stringBuilder.Append("************************Exception End**************************");
            stringBuilder.Append(newLine);
            return stringBuilder;
        }

        /// <summary>
        /// 日志类型
        /// </summary>
        private enum ConsoleWriteStyle { Infor, Warning, Error }

        /// <summary>
        /// 控制台输出信息
        /// </summary>
        static void ConsoleWrite(string title, string infor,
            ConsoleWriteStyle style)
        {
            ConsoleColor old_color = Console.ForegroundColor;
            switch (style)
            {
                case ConsoleWriteStyle.Infor:
                    {
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        Console.Write(title + ":");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        Console.WriteLine(infor);
                        break;
                    }
                case ConsoleWriteStyle.Warning:
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.Write(title + ":");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        Console.WriteLine(infor);
                        break;
                    }
                case ConsoleWriteStyle.Error:
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write(title + ":");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        Console.WriteLine(infor);
                        break;
                    }
            }
            Console.ForegroundColor = old_color;
        }
    }
}
